package cn.edu.sdjzu.xg.eagle.factory;

import cn.edu.sdjzu.xg.eagle.Service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


/**
 * 工厂类：通过硬编码映射关系动态加载 DAO 实现类，支持单例缓存
 */

public class DaoFactory {
    private static final Logger LOGGER = LoggerFactory.getLogger(DaoFactory.class);
    private static final Map<String, Object> DAO_CACHE = new ConcurrentHashMap<>();

    // 硬编码接口与实现类的映射关系
    private static final Map<Class<?>, String> DAO_MAPPING = Map.of(
            DepartmentDaoService.class, "cn.edu.sdjzu.xg.eagle.dao.DepartmentDaoImpl",
            SchoolDaoService.class, "cn.edu.sdjzu.xg.eagle.dao.SchoolDaoImpl",
            TeacherDaoService.class,"cn.edu.sdjzu.xg.eagle.dao.TeacherDaoImpl",
            UserDaoService.class,"cn.edu.sdjzu.xg.eagle.dao.UserDaoImpl",
            CommonDaoService.class,"cn.edu.sdjzu.xg.eagle.dao.CommonDao"
    );

    // 私有构造器，禁止实例化
    private DaoFactory() {}

    /**
     * 获取 DAO 接口的实现类实例（单例）
     * @param daoInterface DAO 接口的 Class 对象
     * @return DAO 实现类的实例
     * @param <T> DAO 接口类型
     * @throws RuntimeException 如果加载失败
     */
    public static <T> T getDao(Class<T> daoInterface) {
        String daoClassName = DAO_MAPPING.get(daoInterface);
        if (daoClassName == null) {
            throw new RuntimeException("未配置接口 " + daoInterface.getSimpleName() + " 的实现类");
        }

        String cacheKey = daoInterface.getName() + ":" + daoClassName;
        Object daoInstance = DAO_CACHE.get(cacheKey);

        if (daoInstance == null) {
            synchronized (DaoFactory.class) {
                daoInstance = DAO_CACHE.get(cacheKey);
                if (daoInstance == null) {
                    daoInstance = createDaoInstance(daoInterface, daoClassName);
                    DAO_CACHE.put(cacheKey, daoInstance);
                }
            }
        }
        return daoInterface.cast(daoInstance);
    }

    /**
     * 反射创建 DAO 实现类实例
     */
    private static <T> T createDaoInstance(Class<T> daoInterface, String daoClassName) {
        try {
            Class<?> clazz = Class.forName(daoClassName);
            if (!daoInterface.isAssignableFrom(clazz)) {
                throw new RuntimeException("类 " + daoClassName + " 未实现接口 " + daoInterface.getName());
            }
            T instance = daoInterface.cast(clazz.getDeclaredConstructor().newInstance());
            LOGGER.debug("已创建 DAO 实例: {}", daoClassName);
            return instance;
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("DAO 类未找到: " + daoClassName, e);
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException("实例化 DAO 类失败: " + daoClassName + " (请检查是否有无参构造方法)", e);
        }
    }
}